 #include "var.h"
#include "utils.h"
#include <stdexcept>
int currentLine=0;

Variable *Alloc(std::string vname, varType vtype, std::map<std::string,Variable*> *v, int &vid)
{
    static int id = 0;

	Variable *n = NULL;

	switch(vtype)
	{
	case INT:
		n = new Int(0, vtype, vname, v);
		break;

	case REAL:
		n = new Real(0, vtype, vname, v);
		break;

	case STRING:
		n = new String(0, vtype, vname, v);
		break;

	case VOID:
		n = new Variable(vtype, vname, v);
		break;

	case PTR:
		n = new Variable(vtype, vname, v);
		break;
	}

    vid = id;
	
	if(v->find(vname)!=v->end())
	{
		std::cout << "~~# ";
		std::cout << "Variable name " << vname << " is already used by " << v[vname]->getName() << " at " << v[vname]->getId();
		return NULL;
	}
	
	/*if(v->size() >= 1)
	{
		for(uint i = 0; i<= v->size()-1; i++)
		{
			try
			{
				if(v->at(i) != NULL)
				{
					if(v->at(i)->getName() == vname)
					{
						std::cout << "~~# ";
						std::cout << "Variable name " << vname << " is already used by " << v->at(i)->getName() << " at " << v->at(i)->getId();
						return NULL;
					}
				}
			}
			catch(std::out_of_range &e)
			{
				std::cerr << e.what() << std::endl;
			}
		}
	}*/

    v->insert(pair<std::string,Variable*>(vname,n);
    id++;
    return n;
}

void Assign(std::map<std::string,Variable*> *v, std::string vname, void *value)
{//il faut changer le assign , a la place de vid il faut vname
    int l = currentLine;
    if(vid > v->size() || vid < 0)
    {
        std::cout << "Error assigning(A0): vid is outside of Variable index bounds at line " << l << std::endl;
        std::cout << "No help available" << std::endl;
        return;
    }

    else if(v == NULL)
    {
        std::cout << "Error assigning(A1): Variable table pointer is NULL at line " << l << std::endl;
        std::cout << "Was the vstack set up?" << std::endl;
        return;
    }

    else if(v[vname] == NULL)
    {
        std::cout << "Error assigning(A2): NULL Variable pointer at line " << l << std::endl;
        std::cout << "Did you allocate space for the vaiable?" << std::endl;
        return;
    }

    else
    {
		v[vname]->setValue(value);
    }

}

std::string vTypeToString(varType vtype)
{
	switch(vtype)
	{
	case INT:
		return "int";
		break;

	case REAL:
		return "real";
		break;

	case STRING:
		return "string";
		break;

	case VOID:
		return "void";
		break;

	case FUNC:
		return "function";
		break;

	case PTR:
		return "pointer";
		break;

	default:
		io()->cmpMsg("Error: Variable type passed to vTypeToString is \ninvalid or not supported yet");
		return "error";
		break;
	}
}

varType StringToVType(std::string stype)
{
	if(stype == "int")
		return INT;
	else if(stype == "real")
		return REAL;
	else if(stype == "function")
		return FUNC;
	else if(stype == "table")
		return TABLE;
	else if(stype == "void")
		return VOID;
	else if(stype == "ptr" || stype == "pointer")
		return PTR;
	else
		return INVALID;
}
